import { Readable } from "stream";
import { CDNClient } from "./CDNClient";
import { CDNClientConfig } from "./CDNConfigs";
import OSS from "ali-oss"

export class AliOSSCDNClient implements CDNClient {
	constructor(config: CDNClientConfig) {
		this.setConfig(config)
		this.init();
	}
	protected config!: CDNClientConfig;
	setConfig(config: CDNClientConfig) {
		this.config = config;
	}

	init(): CDNClient {
		let config = this.config;
		let s3Client = this.s3Client;
		if (s3Client == null) {
			s3Client = new OSS({
				region: config.region,
				accessKeyId: config.accessKeyId,
				accessKeySecret: config.secretAccessKey,
				bucket: config.bucket,
				timeout: 20 * 24 * 3600 * 1000,
			})
			this.s3Client = s3Client
		}

		return this;
	}

	destroy(): Promise<boolean> {
		return Promise.resolve(true)
	}

	protected s3Client!: OSS;
	protected getHeader() {
		const headers = {
			// 指定PutObject操作时是否覆盖同名目标Object。此处设置为true，表示禁止覆盖同名Object。
			'x-oss-forbid-overwrite': `${!this.config.allowOverwirte}`,
		};
		return headers;
	}
	async uploadFile(filepath: string, key: string, readFast: boolean): Promise<string> {
		let config = this.config;
		let s3Client = this.s3Client;

		let result = await s3Client.put(key, filepath, { headers: this.getHeader() })
		return result.url
	}
	async uploadData(key: string, data: string | Buffer, readFast: boolean): Promise<string> {
		let config = this.config;
		let s3Client = this.s3Client;

		if (typeof (data) == "string") {
			data = Buffer.from(data)
		}
		const result = await s3Client.put(key, data, { headers: this.getHeader() })
		return result.url
	}
	async fetchFile(key: string): Promise<Readable> {
		let config = this.config;
		let s3Client = this.s3Client;

		const result = await s3Client.get(key);
		let content = result.content
		let ss = Readable.from(content)
		return ss
	}
	async isExistObject(key: string): Promise<boolean> {
		let s3Client = this.s3Client;
		let config = this.config;

		var isFileExist = true;
		try {
			const existResult = await s3Client.head(key);
		} catch (ex: any) {
			if (ex.code == "NoSuchKey") {
				isFileExist = false;
			}
		}
		return isFileExist;
	}

}
